<script type="text/javascript">
  RED.nodes.registerType('ads-client-subscribe', {
    paletteLabel: 'ADS - Subscribe',
    category: 'TwinCAT ADS',
    icon: 'font-awesome/fa-envelope-o',
    align: 'right',
    color: '#3FADB5',
    inputLabels: function () {
      if (this.variableName === '' && this.controlSubscription) {
        return 'Topic as variable name, subscribe as sub/unsub command'
      } else if (this.variableName === '') {
        return 'Topic as variable name'
      } else {
        return 'Subscribe as sub/unsub command'
      }
    },
    outputs: 1,
    outputLabels: 'Data',
    defaults: { 
      name: { value: '' },
      connection: { value: null, type: "ads-client-connection" },
      variableName: { value: "", required: false },
      cycleTime: { value: 200, required: true },
      mode: { value: 'onchange', rquired: true },
      initialDelay: { value: 0, required: true },
      retryInterval: { value: 2000, required: true },
      controlSubscription: { value: false },
      resubscribeTimeout: { value: 2000 },
      inputs: { value: 0 }
    },
    label: function () {
      if (this.connection === null)
        return `${(this.name || `ADS - Subscribe`)} (*Not configured*)`;

      if (this.name) {
        return this.name
      }

      return `ADS - Subscribe (${(this.variableName === '' ? `msg.topic` : `${this.variableName}`)})`;
    },
    oneditprepare: function () {
      //Stuff that is done when properties panel is opened
      let node = this

      let checkIfInput = function () {
        node.inputs = $('#node-input-variableName').val() === '' || $('#node-input-controlSubscription').is(':checked') ? 1 : 0
      }

      //If variable name is not given -> we need input
      $('#node-input-variableName').change(function () {
        checkIfInput()
      })

      //If checkbox is checked -> we need input
      $('#node-input-controlSubscription').change(function () {
        checkIfInput()
      })
    }
  });
</script>



<!-- Properties -->
<script type="text/html" data-template-name="ads-client-subscribe">
  <div class="form-row">
      <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
      <input type="text" id="node-input-name" placeholder="Name (optional)">
  </div>

  <div class="form-row">
      <label for="node-input-connection"><i class="fa fa-bookmark"></i> ADS connection</label>
      <input type="text" id="node-input-connection" placeholder="ADS Connection">
  </div>

  <div class="form-row">
      <label for="node-input-variableName"><i class="fa fa-tag"></i> Variable name</label>
      <input type="text" id="node-input-variableName" placeholder="Variable name">
  </div>
  <div class="form-tips"><b>Tip:</b> Leave variable name empty to use <code>msg.topic</code> input instead.</div>

  <div class="form-row">
    <!-- Some margin after tip -->
  </div>

  <div class="form-row">
    <label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> Subscription mode</span></label>
    <select id="node-input-mode">
      <option value="onchange">On-change</option>
      <option value="cyclic">Cyclic (send always)</option>
    </select>
  </div>
  
  <div class="form-row">
      <label for="node-input-cycleTime"><i class="fa fa-tag"></i> Cycle time [ms]</label>
      <input type="text" id="node-input-cycleTime" placeholder="Cycle time [ms]">
  </div>
  
  <div class="form-row">
      <label for="node-input-initialDelay"><i class="fa fa-tag"></i> Initial delay [ms]</label>
      <input type="text" id="node-input-initialDelay" placeholder="Initial delay [ms]">
  </div>
  
  <div class="form-row">
      <label for="node-input-retryInterval"><i class="fa fa-tag"></i> Retry interval [ms]</label>
      <input type="text" id="node-input-retryInterval" placeholder="Retry interval [ms]">
  </div>

  <div class="form-row">
    <input type="checkbox" id="node-input-controlSubscription" style="display: inline-block; width: auto; vertical-align: top">
    <label for="node-input-controlSubscription" style="width: 70%"><span>Control subscription with input (<code>msg.subscribe</code>)</span></label>
  </div>
  
  <div class="form-row">
      <label for="node-input-resubscribeTimeout"><i class="fa fa-tag"></i> Resubscribe timeout [ms]</label>
      <input type="text" id="node-input-resubscribeTimeout" placeholder="Resubscribe timeout [ms]">
  </div>
</script>



<!-- Help -->
<script type="text/html" data-help-name="ads-client-subscribe">
  <p>
    Subscribes to given variable to receive notifications.
  </p>


<h3>Properties (settings)</h3>
  <dl class="message-properties">
    <dt>Name
      <span class="property-type">string</span>
    </dt>
    <dd> Optional node name</dd>
  </dl>

  <dl class="message-properties">
    <dt>ADS connection
      <span class="property-type">ads-client-connection</span>
    </dt>
    <dd> ADS client connection (target system) to use</dd>
  </dl>

  <dl class="message-properties">
    <dt>Variable name
      <span class="property-type">string</span>
    </dt>
    <dd> Variable name/path to read</dd>
  </dl>

  <dl class="message-properties">
    <dt>Subscription mode
      <span class="property-type"></span>
    </dt>
    <dd> How to subscribe to the variable (see details)</dd>
  </dl>

  <dl class="message-properties">
    <dt>Cycle time [ms]
      <span class="property-type">number</span>
    </dt>
    <dd> How often the PLC should check if value has changed (or how often to send, see details)</dd>
  </dl>

  <dl class="message-properties">
    <dt>Initial delay [ms]
      <span class="property-type">string</span>
    </dt>
    <dd> How long to wait before sending the first notification</dd>
  </dl>

  <dl class="message-properties">
    <dt>Retry interval [ms]
      <span class="property-type">number</span>
    </dt>
    <dd> If connecting or subscribing fails, how often to try again until success</dd>
  </dl>

  <dl class="message-properties">
    <dt>Control subscription with input
      <span class="property-type">boolean</span>
    </dt>
    <dd> If checked, node subscription is controlled with input (see details)</dd>
  </dl>

  <dl class="message-properties">
    <dt>Resubscribe timeout [ms]
      <span class="property-type">number</span>
    </dt>
    <dd> How long to wait for new notifications after connection loss.
      If no data received in given time, node will try to subscribe again.
    </dd>
  </dl>


<h3>Inputs</h3>
  <dl class="message-properties">
    <dt>topic
      <span class="property-type">undefined | string</span>
    </dt>
    <dd> If given and no variable name set in properties, this topic is used as variable name.</code></dd>
  </dl>

  <dl class="message-properties">
    <dt>subscribe
      <span class="property-type">undefined | boolean</span>
    </dt>
    <dd> If <code>Control subscription with input</code> is checked, this input is used to subscribe/unsubscribe (see details).</code></dd>
  </dl>


<h3>Outputs</h3>
  <dl class="message-properties">
    <dt>payload <span class="property-type">any</span></dt>
    <dd>The value read</dd>
    <dt>type <span class="property-type">object</span></dt>
    <dd>Variable data type information</dd>
    <dt>symbol <span class="property-type">object</span></dt>
    <dd>Variable symbol information</dd>
    <dt>timestamp <span class="property-type">object</span></dt>
    <dd>Variable timestamp</dd>
    <dt>... <span class="property-type">any</span></dt>
    <dd>All input <code>msg</code> properties are forwarded</dd>
  </dl>

<h3>Details</h3>
  <p>
    If mode is <code>on-change</code>, the PLC sends a notification only when value has changed. The notification is sent in <code>cycle time</code> intervals at maximum.
    So if cycle time is 200 ms and the value changes every 10 ms, a new value is still received every 200 ms only.
  </p>
  <p>
    If mode is <code>cyclic</code>, the PLC sends a notification every <code>cycle time</code> interval (even if the value hasn't changed).
    So if cycle time is 200 ms and the value changes every 10 seconds, a new value is still received every 200 ms.
  </p>
  <p>
    <b>Note:</b> With default settings the node has no input as it's not needed.
  </p>
  <p>
    If the variable name is not set in properties, the input <code>msg.topic</code> is used as variable name instead.
  </p>
  <p>
    If the <code>Control subscription with input</code> is checked, the node doesn't subscribe automatically.
    It will subscribe only when receiving input <code>msg.subscribe</code> that has truthy value (like <code>true</code>, <code>1</code>..).
    The node can then be unsubscribed by giving a non-truthy value (like <code>false</code>, <code>0</code>..) to input <code>msg.subscribe</code>.
  </p>
  <p>
    See <code>ads-client</code> readme for help. Valid variable name for TwinCAT 3 can be something like <code>GVL.VariableName</code>
  </p>


<h3>References</h3>
  <ul>
    <li><a href="https://github.com/jisotalo/ads-client#subscribing-to-plc-variables-device-notifications" target="_blank" style="text-decoration: underline">
      ads-client subscribe() readme
    </a></li>
    <li><a href="https://jisotalo.github.io/ads-client/Client.html#subscribe" target="_blank" style="text-decoration: underline">
      ads-client subscribe() documentation
    </a></li>
  </ul>
</script>